﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace AutoF3
{
    public partial class ProblemTypeForm : Form
    {
        List<ProblemRetriever> pr;
        SheetBuilder sb;
        Dictionary<TreeNode, ProblemRetriever> treeNodeRetrieverDict = new Dictionary<TreeNode, ProblemRetriever>();
        private TreeNode randomNode;

        public ProblemTypeForm(List<ProblemRetriever> pr, SheetBuilder sb)
        {
            InitializeComponent();
            this.pr = pr;
            this.sb = sb;
            GenerateTreeView();
        }

        private void GenerateTreeView()
        {
            randomNode = retrieverCategoryTreeView.Nodes.Add("Random");

            var categoryBreadCrumbTreeNodeDict = new Dictionary<string, TreeNode>(); //(categorybreadcrumb, node representing that position in tree) 
            var categoryListProblemRetrieverDict = new Dictionary<List<string>, ProblemRetriever>();

            var categoryLists = new List<List<string>>();
            foreach (var retriever in pr)
            {
                categoryLists.Add(retriever.GetCategoryList());
                categoryListProblemRetrieverDict[retriever.GetCategoryList()] = retriever;
            }

            int length = categoryLists.Count;
            if (length > 0)
            {
                foreach (var list in categoryLists) //redundancy; make sure doesn't already exist
                    if (!categoryBreadCrumbTreeNodeDict.ContainsKey(list[0]))
                        categoryBreadCrumbTreeNodeDict[list[0]] = retrieverCategoryTreeView.Nodes.Add(list[0]);
                
                foreach (var list in categoryLists)
                {
                    string currCatBreadcrumb = list[0];

                    for (int i = 1; i < list.Count; i++)
                    {
                        TreeNode node = categoryBreadCrumbTreeNodeDict[currCatBreadcrumb]; //this is the parent category node of the category we will add
                        var newNode = node.Nodes.Add(list[i]);
                        currCatBreadcrumb += list[i];
                        categoryBreadCrumbTreeNodeDict[currCatBreadcrumb] = newNode;

                        if (i == list.Count - 1)
                            treeNodeRetrieverDict[newNode] = categoryListProblemRetrieverDict[list];
                    }
                }
            }

            retrieverCategoryTreeView.ExpandAll();
        }

        private void AddButton_Click(object sender, EventArgs e)
        {
            AddButton.Enabled = false;
            retrieverCategoryTreeView.Enabled = false;

            TreeNode node = retrieverCategoryTreeView.SelectedNode;
            ProblemRetriever retriever;

            if (node.Equals(randomNode))
            {
                Random random = new Random();
                retriever = pr[random.Next(pr.Count)];
            }
            else if (node.Nodes.Count > 0) //ensure we use a bottom-level node
            {
                var currNode = node;
                Random random = new Random();
                while (currNode.Nodes.Count > 0)
                    currNode = currNode.Nodes[random.Next(currNode.Nodes.Count)];
                retriever = treeNodeRetrieverDict[currNode];
            }
            else
                retriever = treeNodeRetrieverDict[node];

            backgroundWorker1.RunWorkerAsync(retriever);
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            var retriever = (ProblemRetriever)e.Argument;

            int numToRetrieve;
            try
            {
                numToRetrieve = Convert.ToInt32(numProblemsBox.Text);
                numToRetrieve = Math.Min(50, numToRetrieve); //TODO: remove this hard limit and change forumretriever class to use >1 page
            }
            catch
            {
                numToRetrieve = 20;
            }

            var problems = retriever.RetrieveProblems(numToRetrieve);
            e.Result = problems;
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            var problemList = (List<Problem>)e.Result;
            var editProblem = new AddProblemForm(problemList, sb);
            editProblem.ShowDialog();
            this.Close();
        }

        private void retrieverCategoryTreeView_AfterSelect(object sender, TreeViewEventArgs e)
        {
            if (retrieverCategoryTreeView.SelectedNode == null)
                AddButton.Enabled = false;
            else
                AddButton.Enabled = true;
        }
    }
}
